#pragma once

#include "BitMap.h"

typedef unsigned int(*HashFuncType)(const char *, unsigned int);

typedef struct BloomFilter {
	BitMap	bm;
	HashFuncType	func1;
	HashFuncType	func2;
	HashFuncType	func3;
}	BloomFilter;

unsigned int SDBMHash(char *str, unsigned int size)
{
	unsigned int hash = 0;

	while (*str)
	{
		// equivalent to: hash = 65599*hash + (*str++);
		hash = (*str++) + (hash << 6) + (hash << 16) - hash;
	}

	return (hash & 0x7FFFFFFF) % size;
}

// RS Hash Function
unsigned int RSHash(char *str, unsigned int size)
{
	unsigned int b = 378551;
	unsigned int a = 63689;
	unsigned int hash = 0;

	while (*str)
	{
		hash = hash * a + (*str++);
		a *= b;
	}

	return (hash & 0x7FFFFFFF) % size;
}

// JS Hash Function
unsigned int JSHash(char *str, unsigned int size)
{
	unsigned int hash = 1315423911;

	while (*str)
	{
		hash ^= ((hash << 5) + (*str++) + (hash >> 2));
	}

	return (hash & 0x7FFFFFFF) % size;
}

void BFInit(BloomFilter *pBF, unsigned int size)
{
	/* BMInit(&(pF->bm), size); */
	BMInit(&(pBF->bm), size);
	pBF->func1 = SDBMHash;
	pBF->func2 = RSHash;
	pBF->func3 = JSHash;
}

void BFInsert(BloomFilter *pBF, const char *str)
{
	unsigned int i1 = pBF->func1(str, pBF->bm.size);
	unsigned int i2 = pBF->func2(str, pBF->bm.size);
	unsigned int i3 = pBF->func3(str, pBF->bm.size);

	BMSetOne(&(pBF->bm), i1);
	BMSetOne(&(pBF->bm), i2);
	BMSetOne(&(pBF->bm), i3);
}

int BFIsExist(BloomFilter *pBF, const char *str)
{
	unsigned int i1 = pBF->func1(str, pBF->bm.size);
	unsigned int i2 = pBF->func2(str, pBF->bm.size);
	unsigned int i3 = pBF->func3(str, pBF->bm.size);

	return BMTestOne(&(pBF->bm), i1) && BMTestOne(&(pBF->bm), i2)
		&& BMTestOne(&(pBF->bm), i3);
}

